<!--
 * @Author: 甘国炎 gangy@yusys.com.cn
 * @Date: 2023-04-12 16:13:56
 * @LastEditors: 甘国炎 gangy@yusys.com.cn
 * @LastEditTime: 2023-04-12 16:14:10
 * @FilePath: \canadia-tmf-mbankd:\code\js\bigFileUp.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
    <div>
      <form action="">
        <input type="file" @change="handleFileChange($event)" />
        <button @click.prevent="handleFileUpload()">上传</button>
      </form>
    </div>
  </template>
  <script>
  import axios from "axios";
  axios.defaults.baseURL = "http://localhost:3000";
  export default {
    data() {
      return {
        file: null,
      };
    },
    methods: {
      handleFileChange(event) {
        const file = event.target.files[0];
        if (!file) return;
        this.file = file;
      },
      // 1、创建切片
      createFileChunks(size = 1024 * 100) {
        // 创建数组，存储文件的所有切片
        let fileChunks = [];
        for (let cur = 0; cur < this.file.size; cur += size) {
          // file.slice 方法用于切割文件，从 cur 字节开始，切割到 cur+size 字节
          fileChunks.push(this.file.slice(cur, cur + size));
        }
        return fileChunks;
      },
      /**
       * 2、拼接 formData
       * 参数1：存储文件切片信息的数组
       * 参数2：上传时的文件名称
       */
      concatFormData(fileChunks, filename) {
        /**
         * map 方法会遍历切片数组 fileChunks中的元素map 方法会遍历切片数组 fileChunks中的元素,
         * 数组中有多少个切片，创建几个 formData，在其中上传的文件名称、hash值和切片，并将此 formData
         * 返回，最终chunksList中存储的就是多个 formData(每个切片对应一个 formData)
         *
         */
        const chunksList = fileChunks.map((chunk, index) => {
          let formData = new FormData();
          // 这个'filename' 字符串的名字要与后端约定好
          formData.append("filename", filename);
          // 作为区分每个切片的编号，后端会以此作为切片的文件名称，此名称也应该与后端约定好
          formData.append("hash", index);
          // 后端会以此作为切片文件的内容
          formData.append("chunk", chunk);
          return {
            formData,
          };
        });
        return chunksList;
      },
      // 3、上传切片
      async uploadChunks(chunksList) {
        const uploadList = chunksList.map(({ formData }) =>
          axios({
            method: "post",
            url: "/upload",
            data: formData,
          })
        );
        await Promise.all(uploadList);
      },
  
      // 大文件上传
      async handleFileUpload() {
        console.log(1);
        const file = this.file;
        if (!file) return;
        // 1、切片切割，第二个参数采用默认值
        const fileChunks = this.createFileChunks();
        // 2、将切片信息拼接成 formData 对象
        const chunksList = this.concatFormData(fileChunks, this.file.name);
        // 3、上传切片
        await this.uploadChunks(chunksList);
        // 4、所有切片上传成功后后，再告诉后端所有切片都已完成
        await this.mergeFileChunks(this.file.name);
        console.log("上传完成");
      },
  
      // 合并切片
      async mergeFileChunks(filename) {
        await axios({
          method: "get",
          url: "/merge",
          params: {
            filename,
          },
        });
      },
    },
  };
  </script>